package com.bjpowernode.money.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.bjpowernode.money.constant.UserConstant;
import com.bjpowernode.money.model.BidInfo;
import com.bjpowernode.money.model.LoanInfo;
import com.bjpowernode.money.model.User;
import com.bjpowernode.money.service.BidInfoService;
import com.bjpowernode.money.service.LoanInfoService;
import com.bjpowernode.money.utils.Result;
import com.bjpowernode.money.utils.ReturnCode;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author ZHAOZHENYU
 * @since 2022/10/21
 * 投资控制器
 */
@Controller
public class BidController {

    @Reference(interfaceClass = BidInfoService.class, version = "1.0.0", timeout = 20000)
    private BidInfoService bidInfoService;

    @Reference(interfaceClass = LoanInfoService.class, version = "1.0.0", timeout = 20000)
    private LoanInfoService loanInfoService;

    /**
     * 1、投资
     * @param loanId
     * @param bidMoney
     * @param request
     * @return
     */
    @PostMapping("/bid/invest")
    @ResponseBody
    public Object invest(@RequestParam(name = "loanId",required = true) Integer loanId,
                         @RequestParam(name = "bidMoney",required = true) Double bidMoney,
                         HttpServletRequest request){
        //是否登录
        User user_session = (User) request.getSession().getAttribute(UserConstant.LOGIN_USER);
        if (!ObjectUtils.allNotNull(user_session)) {
            return Result.error("未登录");
        }
        // 是否实名认证
        String name = user_session.getName();
        String idCard = user_session.getIdCard();
        if (!ObjectUtils.allNotNull(name,idCard)) {
            return Result.error("未实名认证");
        }
        //基础验证
        //业务验证：防止前台验证未刷新数据出错
        LoanInfo loanInfo = loanInfoService.queryLoanInfoById(loanId);
        Double bidMinLimit = loanInfo.getBidMinLimit();
        Double bidMaxLimit = loanInfo.getBidMaxLimit();
        Double leftProductMoney = loanInfo.getLeftProductMoney();
        if (bidMoney < bidMinLimit || bidMoney > bidMaxLimit) {
            return Result.error("投资金额必须在" + bidMinLimit + "-" + bidMaxLimit + "之间");
        }
        // 超卖问题  改为手动事务回滚，不更新数据时事务生效
        /*if (bidMoney > leftProductMoney) {
            return Result.error("投资金额超过剩余募集金额：" + leftProductMoney );
        }*/

        // 投资：插入数据库 获得各种错误结果的状态码
        int result = 0;
        try {
            // version乐观锁解决并发投资数据不一致问题
            result = bidInfoService.invest(loanId,bidMoney,user_session.getId());
            // 加锁解决：锁是LoanInfo
//            result = bidInfoService.investConcurrency(loanId,bidMoney,user_session.getId());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("服务器忙碌，请稍后尝试");
        }
        if (result != ReturnCode.BID_SUCCESS) {
            switch (result){
                case ReturnCode.BID_LOAN_MONEY_UPDATE_FAIL:
                    return Result.error("减少剩余可投金额失败");
                case ReturnCode.BID_LOAN_INFO_INSERT_FAIL:
                    return Result.error("更新产品满标状态失败");
                case ReturnCode.BID_FINANCE_MONEY_UPDATE_FAIL:
                    return Result.error("减少账户余额失败");
                case ReturnCode.BID_INFO_INSERT_FAIL:
                    return Result.error("添加投资记录失败");
                default:
                    return Result.error("投资失败");
            }
        }else {
            return Result.success();
        }

        // TODO：模拟千人并发投资
        /*for (int i = 0; i < 1000; i++) {
            ThreadPoolManager.getThreadPoolExecutor().execute(new Runnable() {
                @Override
                public void run() {
                    // 添加同步解决
//                    bidInfoService.investConcurrency(loanId, bidMoney, user_session.getId());
                    // 添加悲观锁解决，version字段
                    bidInfoService.invest(loanId, bidMoney, user_session.getId());
                }
            });
        }
        return Result.success();*/

    }

    /**
     * 2、异步加载投资排行榜,变成json传过去，在后端按金额排好序
     * @return
     */
    @GetMapping("/loan/bid/rankList")
    @ResponseBody
    public Object bidRankList(){

        List<BidInfo> bidInfoList = loanInfoService.queryBidRankList();

        return bidInfoList;
    }

}
